package org.dgm.nw.core.control;

import org.apache.log4j.Logger;
import org.dgm.nw.core.exception.SystemUnInitableException;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractRefreshableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * spring动态bean工厂。<br>
 * 实例化时先从spring ioc工厂中寻找，若不存在，则注册
 * 
 * @author wangwz
 * @date Aug 31, 2010
 * @version RCS: $Id: SpringBeanFactory.java 400873 2011-01-17 04:14:03Z wangwz $
 */
public class SpringBeanFactory {
	/**
	 * Logger for this class
	 */
	private static final Logger log = Logger 
			.getLogger(SpringBeanFactory.class);

	private static SpringBeanFactory beanFactory;
	private ApplicationContext ac;

	// 单例模式，私有化
	private SpringBeanFactory() {

	}

	/**
	 * 初始化springBean工厂
	 * 
	 * @param applicationContextPath
	 *            配置文件名，多个用半角逗号隔开；文件放置在classpath路径下
	 * @throws SystemUnInitableException
	 */
	public static void init(String applicationContextPath)
			throws SystemUnInitableException {
		if (beanFactory != null) {// 只需初始化一次
			return;
		}

		try {
			beanFactory = new SpringBeanFactory();
			beanFactory.ac = new ClassPathXmlApplicationContext(applicationContextPath.split(",", -1));
		} catch (Exception e) {
			log.fatal("spring初始化失败.", e);
			throw new SystemUnInitableException("spring初始化失败.", e);
		}

	}

	/**
	 * 初始化springBean工厂,采用默认值<br>
	 * 此种默认模式的正则运算加载在tomcat下可用，但在weblogic下会出现问题
	 * 
	 * @throws SystemUnInitableException
	 * @deprecated
	 * 
	 */
	public static void init() throws SystemUnInitableException {
		init("applicationContext-*.xml");
	}

	/**
	 * 获取单例方法
	 * 
	 * @return
	 */
	public static SpringBeanFactory getBeanFactory() {
		return beanFactory;
	}

	/**
	 * 创建新的实例（非单例）
	 * 
	 * @param beanClass
	 * @param autoWrie
	 *            是否自动装载
	 * @return
	 */
	public Object createBean(Class beanClass) {
		return getBean("NEW_" + beanClass.getName(), beanClass, false, null);
	}

	/**
	 * 创建新的实例（非单例）
	 * 
	 * @param beanClass
	 * @param args
	 *            构造函数参数
	 * @return
	 */
	public Object createBean(Class beanClass, Object[] args) {
		return getBean("NEW_" + beanClass.getName(), beanClass, false, args);
	}

	/**
	 * 根据定义的beanname获取实例
	 * 
	 * @param beanName
	 * @param beanClass
	 * @param autoWrie
	 *            是否自动重写
	 * @param isSingle
	 *            是否单例
	 * @return
	 */
	public Object getBean(String beanName, Class beanClass, boolean isSingle,
			Object[] arguments) {
		DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) ((AbstractRefreshableApplicationContext) ac)
				.getBeanFactory();
		if (beanFactory.containsBean(beanName)) {// 如果spring已定义，则返回实例
			log.info("spring已注册"+beanName+",直接返回");
			return beanFactory.getBean(beanName);
		}

		RootBeanDefinition beanDefinition = new RootBeanDefinition();
		beanDefinition.setBeanClass(beanClass);
		beanDefinition.setAutowireCandidate(true);
		beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_NO);// 不自动装载

		if (arguments != null && arguments.length > 0) {
			ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
			for (int i = 0; i < arguments.length; i++) {
				constructorArgumentValues.addIndexedArgumentValue(i,
						arguments[i]);
				beanDefinition
						.setConstructorArgumentValues(constructorArgumentValues);
			}
		}

		if (!isSingle) {
			beanDefinition.setScope(AbstractBeanDefinition.SCOPE_PROTOTYPE);
		} else {
			beanDefinition.setScope(AbstractBeanDefinition.SCOPE_SINGLETON);
		}

		log.info("spring 注册"+beanName+"");
		beanFactory.registerBeanDefinition(beanName, beanDefinition);// 向spring容器中注册

		return beanFactory.getBean(beanName);
	}

	/**
	 * 实例化对象（在容器中注册，用类名作为beanname)
	 * 
	 * @param beanClass
	 * @return
	 */
	public Object getBean(Class beanClass) {
		return getBean(beanClass.getName(), beanClass, true, null);
	}

	/**
	 * 实例化对象（在容器中注册，用类名作为beanname)
	 * 
	 * @param beanClass
	 * @param args
	 *            构造函数入参
	 * @return
	 */
	public Object getBean(Class beanClass, Object[] args) {
		return getBean(beanClass.getName(), beanClass, true, args);
	}

	/**
	 * 从配置中获取spring的配置bean
	 * 
	 * @param name
	 * @return
	 */
	public Object getConfigBean(String name) {
		return ac.getBean(name);
	}
}